import React, {createRef} from 'react';
import styles from './index.module.scss';
import EditChartContainer from "./EditChartContainer";
import EnumOnFire from "@/pages/dv/constants/EnumOnFire";
import {EE, prompt} from "@/utils";
import {round, debounce, throttle} from 'lodash';
import dvTool from "@/pages/dv/dvTool";
import drawTool from "@/pages/dv/drawTool";
import * as classnames from "classnames";
import ResizeObserver from 'resize-observer-polyfill';
import Ruler from "./Ruler";
import {addListener} from '../../../helper/listener';
import ResizeTool from '../../../helper/resizeTool';


interface IProps {

}

interface IState {
  charts?: {
    [key: string]: DV.IChart
  };
  bgConfig?: DV.IBgConfig | {};
  dvOption?: object | {};
  containerWidth?: number
  containerHeight?: number
  scale?: number;
  startX?: number;
  startY?: number;
}

/**
 * 大屏展示组件
 * @param uuid
 * @param adapterMode
 * @param option
 * @param props
 * @constructor
 */

class BoxContainer extends React.PureComponent<IProps, IState> {
  public dvContainerRef: any;
  public bgRef: any;
  public dvRealBoxRef: any;
  public editorContainerRef: any;
  public isHover: boolean;
  public drawOuterBox: any;
  public $screens: any;
  public $screensContainer: any;
  public thick: number;

  constructor(props: IProps) {
    super(props);
    this.dvContainerRef = null;
    this.dvRealBoxRef = null;
    this.editorContainerRef = null;
    this.drawOuterBox = null;
    this.$screens = null;
    this.$screensContainer = null;
    this.isHover = !!dvTool.selectedChartKey;
    this.state = {
      charts: dvTool.charts,
      containerWidth: 0,
      containerHeight: 0,
      scale: dvTool.scale,
      startX: 0,
      startY: 0,
    }
    this.thick = 16;
    this.handleWheel = throttle(this.handleWheel, 100)
  }

  componentDidMount(): void {

    // 初始化缩放级别
    this.initScale();

    // 初始化 标尺
    this.initRuler();

    // 初始化 键盘事件
    this.initMouseAction();

    // 初始化 配置更新订阅
    this.initFireEvents();

    // 初始化辅助线画板
    drawTool.initScreenContainer(this.$screensContainer);
  }

  initFireEvents() {
    // 开启绘画编辑模式
    EE.on(EnumOnFire.drawChart_emit, (type: DV.IChartType, uid: string) => {

      this.drawOuterBox.style.display = 'block';
      drawTool.drawChartRect(this.drawOuterBox, dvTool.scale, {
        onFinish: (left: number, top: number, width: number, height: number, isDrawEnd: boolean) => {
          if(uid){
            // 复制组件
            dvTool.copyChartOption(uid, {
              left, top, width, height
            }, isDrawEnd);
          } else {
            // 新增组件
            dvTool.addChartOption(type, {
              left, top, width, height
            }, isDrawEnd);
          }

        }
      })
    });

    EE.on(EnumOnFire.drawChart_status, (status: string) => {
      if(status === 'end')  this.drawOuterBox.style.display = 'none';
    });


    EE.on(EnumOnFire.addChart, () => {
      this.forceUpdate()
    });

    EE.on(EnumOnFire.deleteChart, () => {
      this.forceUpdate()
    });


    EE.on(EnumOnFire.updateBgConfig, (bgConfig: DV.IBgConfig) => {
      this.bgRef.style.backgroundColor = bgConfig.bgColor;
      this.bgRef.style.filter = `blur(${bgConfig.bgBlur}px)`;
      this.bgRef.style.opacity = bgConfig.bgOpacity;
      this.bgRef.style.backgroundImage = `url(${bgConfig.bgUrl})`;
    });
  }

  /**
   * 初始化缩放级别
   */
  initScale() {

    EE.on(EnumOnFire.changeScale, (scale: number) => {
      this.changeAdapter(scale, () => {
        this.handleScroll()
      });
    });

    const containerHeight = this.editorContainerRef.offsetHeight - 60 - 30;
    const containerWidth = this.editorContainerRef.offsetWidth - 50 - 30;
    const initScaleY = round(containerHeight / dvTool.dvOption.height, 2);
    const initScaleX = round(containerWidth / dvTool.dvOption.width, 2);
    const initScale = initScaleY > initScaleX ? initScaleX : initScaleY;
    // 更新缩放级别
    dvTool.changeScale(initScale);

    // 初始化 缩放事件
    this.editorContainerRef.addEventListener('mousewheel', (event: any) => {
      if (event.ctrlKey === true || event.metaKey) {
        event.preventDefault();

        this.handleWheel(event.deltaY)
      }
    }, {passive: false})
  }

  /**
   * 缩放
   * @param deltaY
   */
  handleWheel = (deltaY: number) => {
    if (deltaY > 0) {
      // zoom 缩小
      // // 更新缩放级别
      dvTool.changeScale(dvTool.scale - 0.03);
    } else if (deltaY < 0) {
      // zoom 放大
      // // 更新缩放级别
      dvTool.changeScale(dvTool.scale + 0.03);
    }
  }

  /**
   * 初始化-标尺
   */
  initRuler() {
    this.setState({
      containerWidth: this.editorContainerRef.offsetWidth,
      containerHeight: this.editorContainerRef.offsetHeight,
    })
    //
    this.$screensContainer.style.width = dvTool.dvOption.width * 2 + 500 + 'px';
    this.$screensContainer.style.height = dvTool.dvOption.height * 2 + 500 + 'px';
    // 滚动居中
    this.$screens.scrollLeft = 200 - 50;  // 200 = #dv_container.left
    this.$screens.scrollTop = 200 - 40;  // 200 = #dv_container.top

    // 监听尺寸变化，动态更新标尺
    ResizeTool.init(ResizeObserver, () => {
      ResizeTool.resizeObserver(this.editorContainerRef, {
        refreshMode: 'throttle',
        onResize: ({width, height}) => {
          this.setState({
            containerWidth: width,
            containerHeight: height,
          })
        }
      })
    });
  }

  initMouseAction() {
    dvTool.MouseAction.bind('right', (e, combo) => {
      if (this.isHover) {
        e.preventDefault();
        dvTool.moveChartPosition({x: 1});
      }
    })
    dvTool.MouseAction.bind('left', (e, combo) => {
      if (this.isHover) {
        e.preventDefault();
        dvTool.moveChartPosition({x: -1});
      }
    })
    dvTool.MouseAction.bind('up', (e, combo) => {
      if (this.isHover) {
        e.preventDefault();
        dvTool.moveChartPosition({y: -1});
      }
    })
    dvTool.MouseAction.bind('down', (e, combo) => {
      if (this.isHover) {
        e.preventDefault();
        dvTool.moveChartPosition({y: 1});
      }
    })
  }

  /**
   * 改变适配方案--默认等比缩放
   */
  changeAdapter = (scale: number, cb: Function) => {
    try {
      this.setState({
        scale
      }, () => {
        if (typeof cb === 'function') cb();
      })
      this.dvContainerRef.style.transform = 'scale(' + scale + ')';
    } catch (e) {

    }
  }

  onMouseEnter = () => {
    this.isHover = true;
  }

  onMouseLeave = () => {
    this.isHover = false;
  }

  handleScroll = () => {

    const screensRect = this.$screens.getBoundingClientRect()
    const dvRect = this.dvContainerRef.getBoundingClientRect();


    // 标尺开始的刻度
    const {scale} = this.state
    // 55px是顶部留白padding
    const startX = (screensRect.left + this.thick - dvRect.left) / scale;
    // 35px是顶部留白padding
    const startY = (screensRect.top + this.thick - dvRect.top) / scale;

    this.setState({startX, startY})
  }

  drawSvgRect() {
    return <svg viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" width="100" height="100">
      <rect
        width="300"
        height="100"
        style={{
          fill: 'deepskyblue',
          strokeWidth: 2,
          stroke: 'rgba(255,0,0, 1)',
          fillOpacity: 0.5,
          strokeOpacity: 0.9,
          opacity: 0.5
        }}/>
    </svg>
  }


  render(): React.ReactNode {
    const {bgConfig, dvOption} = dvTool;
    const {containerWidth, containerHeight, scale, startX, startY} = this.state;

    return <div
      className={styles.dv_editor_container + ' scrollbar_theme'}
      ref={e => this.editorContainerRef = e}
      id="dv_edit_container"
    >

      {/*标尺外容器*/}
      <Ruler
        width={containerWidth}
        height={containerHeight}
        scale={scale}
        startX={startX}
        startY={startY}
        // dvWidth={}
      />
      {/*标尺内容容器*/}
      <div
        className={styles.screens}
        ref={e => this.$screens = e}
        onScroll={this.handleScroll}
      >
        <div className={styles.screens_container} ref={e => this.$screensContainer = e} id={'screensContainer'}>

          {/*大屏容器*/}
          <div
            className={'dv_container'}
            id="dv_container"
            ref={e => this.dvContainerRef = e}
            style={{
              width: dvOption.width,
              height: dvOption.height
            }}
            onMouseEnter={this.onMouseEnter}
            onMouseLeave={this.onMouseLeave}
          >
            {/*新增组件时展示区画板*/}
            <div
              className={styles.drawOuterBox}
              ref={e => this.drawOuterBox = e}
              style={{
                background: `url(${this.drawSvgRect()}) repeat`
              }}
            >

            </div>

            {/*大屏背景*/}
            <div
              className={'dv_bg'}
              ref={e => this.bgRef = e}
              style={{
                backgroundImage: `url(${bgConfig.bgUrl})`,
                backgroundColor: bgConfig.bgColor,
                opacity: bgConfig.bgOpacity,
                filter: `blur(${bgConfig.bgBlur}px)`, // 高斯模糊
              }}
            />
            {/*图表组件渲染*/}
            <div className={'dv_chart_list'}>
              {
                Object.values(this.state.charts).map((chartOption: DV.IChart, index: number) => <EditChartContainer
                  key={chartOption.uid ? chartOption.uid : index}
                  chartOption={chartOption}
                />)
              }
            </div>
          </div>
        </div>
      </div>


    </div>
  }

}

export default BoxContainer;


